package com.qst.gateway.filter;


import com.qst.domain.util.JwtUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;

/*这里统一说一下
浏览器在请求时，如果为复杂请求（非get请求或者请求头中有额外数据时，）
则预先发一个option请求检测此请求是否能不能通过，此option请求只会包含原本请求的请求类型 额外请求头等信息，并不会包含token
此过滤器会拦截此请求 导致原请求停留在浏览器中不会被发送过来
一个简单方法即为当请求发送过来的时候判断是否为option请求 如果为则直接通过，保持预检一直成立
不为则判断请求头中的token是否正确 如果是对应token则放行，否则拦截
*/


@Component
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {

    public AuthorizeGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("role");
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
            if(request.getMethod().equals(HttpMethod.OPTIONS)){
                return chain.filter(exchange);
            }
            Integer role = config.getRole();
            HttpHeaders headers = request.getHeaders();
            String token = request.getHeaders().getFirst("Authorization");
            Integer role1 = JwtUtils.getMemberRoleByJwtToken(token);
            if(role==role1){
                ServerHttpRequest build = request.mutate().header("id", String.valueOf(JwtUtils.getMemberIdByJwtToken(token))).build();
                ServerWebExchange webExchange = exchange.mutate().request(build).build();
                return chain.filter(webExchange);
            }else {
                response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);
                return response.setComplete();
            }

        };
    }

    public static class Config {
        private Integer role;

        public Integer getRole() {
            return role;
        }

        public void setRole(Integer role) {
            this.role = role;
        }
    }
}
